#!/usr/bin/env ruby

# require EXIF reader
require "exifr"

#
# Exif information handler
#
class ExifHandler
    
  # DEBUG function, show exif information
  # @returns nothing unless no exif information is found
  def showdata(image)
    exifdata = Array.new
    
    image_file = image
    
    exif_info = EXIFR::JPEG.new(image_file)
    
    if(!exif_info.exif?)
      return 0
    end
    
    puts "Standard items".center(72)
    puts "=" * 72
    puts "                          File : #{image_file}"
    puts "                        Height : #{exif_info.height}"
    puts "                         Width : #{exif_info.width}"
    puts

    if exif_info.exif? then
        puts "EXIF information".center(72)
        puts "=" * 72
        h = exif_info.exif.to_hash
        h.each_pair do |k,v|
            puts "#{k.to_s.rjust(30)} : #{v}"
        end
    else
        puts "No EXIF information in this image"
    end
  end
  
  # get exif information
  # @returns array with
  #  filename, date_time, category,
  #  gps_latitude, gps_latitude_ref, gps_longitude, gps_longitude_ref
  def get_exif(image)
    # return array
    exifdata = Array.new
    
    image_file = image
    
    # create exif info object
    exif_info = EXIFR::JPEG.new(image_file)
    
    # check if there is exif information
    if(!exif_info.exif?)
      return false
    end
    
    # convert exif data to hash 
    h = exif_info.exif.to_hash
    
    
    # retrieve wanted information
    filename = image.split("\\").last
    date_time = h[:date_time_original]
    date_time = self.format_date_in(date_time)
    category = h[:image_description]
    
    # add gps location information
    if(h[:gps_latitude])
      gps = true 
      gps_latitude = self.dms2dec(h[:gps_latitude][0], h[:gps_latitude][1], h[:gps_latitude][2], h[:gps_latitude_ref])
      
      gps_latitude_ref = h[:gps_latitude_ref]
  
      gps_longitude = self.dms2dec(h[:gps_longitude][0], h[:gps_longitude][1], h[:gps_longitude][2], h[:gps_longitude_ref])
      
      gps_longitude_ref = h[:gps_longitude_ref]
    end

    # add to returned object array
    exifdata.push(filename)
    exifdata.push(date_time)
    exifdata.push(category)
    
    # add gps data
    if gps
      exifdata.push(gps_latitude)
      exifdata.push(gps_latitude_ref)
      exifdata.push(gps_longitude)
      exifdata.push(gps_longitude_ref)      
    end

    return exifdata
  end
  
  # converts gps DMS to decimal value
  #@returns decimal value
  def dms2dec(deg, min, sec, ref)
    # calculate total number of seconds
    seconds = ((min * 60) + sec.to_f)
    seconds = (seconds / 3600)
    # add fractional degrees to whole degrees for final result
    result = deg + seconds
    
    # check if West of South degree, negate
    if ref[0,1] == "W" || ref[0,1] == "S"
      result = -result
    end
    
    return result 
  end
  
  # converts gps decimal to DMS
  def dec2dms(float)
    # conpute degrees, minutes and seconds
    deg = long.to_i
    minfloat = 60 * (float - deg)
    min = minfloat.to_i
    secfloat = 60 * (minfloat  min)
    
    # seconds to desired precision
    secfloat = "%.5f" % secfloat
    
    # seconds might become 60
    if secfloat >= 60
      min = min + 1
      secfloat = secfloat - 60
    end
    
    if min >= 60
      deg = deg + 1
      min = min - 60
    end
    
    return deg, min, secfloat
  end

  # function to format time and date from the form:
  # Day Mnt #Day HH:MM:SS #timezone #year
  def format_date_in(date)
    r = 0
    
    if date != nil 
      date = date.to_s
      time_array = date.split(' ')
      
      day = time_array[0]
      month = time_array[1]
      day = time_array[2]
      time = time_array[3]
      timezone = time_array[4]
      year = time_array[5]
      
      # month lookup
      month_corr = {"Jan" => 1, "Feb" => 2, "Mar" => 3, "Apr" => 4,
                    "May" => 4, "Jun" => 6, "Jul" => 7, "Aug" => 8,
                    "Sep" => 9, "Oct" => 10, "Nov" => 11, "Dec" => 12}
      
      month = month_corr["#{month}"]
      
      r = "%2s.%02d.%4s %s " % [day, month, year, time]
    end
    
    return r
    
  end
  
  # function to read date and time string
  # returns array with (day, month, year, time)
  def format_date_out(date)
    
    if date.nil?
      return 0
    end

    tmp = date.split('.')
    
    day = tmp[0]
    month = tmp[1]
    
    tmp2 = tmp[2].split(' ')
    year = tmp2[0]
    time = tmp2[1]
    
    return day, month, year, time
  end
  

end
